﻿// ------------------------------------------------------------------------
// 项目名称：Canroc.Net 
// 版权归属：Canroc（https://gitee.com/canroc）
//
// 许可证信息
// Canroc.Net项目主要遵循 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-APACHE 文件。
//
// 使用条款：
// 1.使用本项目应遵守相关法律法规和许可证的要求。
// 2.不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动。
// 3.任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任
//
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
//
// 其他重要信息
// Canroc.Net 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// ------------------------------------------------------------------------

using Canroc.Net.Application.SysFileService.Dto;
using System.Net.Mime;

// ReSharper disable once CheckNamespace
namespace Canroc.Net.Application.SysFileService;

/// <summary>
///     系统文件应用服务
/// </summary>
[ApiDescriptionSettings("System")]
public partial class SysFileAppService(SqlSugarRepository<SysFile> fileRep) : IDynamicApiController, ITransient
{
    /// <summary>
    ///     上传文件
    /// </summary>
    /// <returns></returns>
    public async Task<FileModel> UploadAsync(IFormFile file)
    {
        if (file is null)
            throw Oops.Oh(ErrorCodeEnum.NotFile);

        // 文件名称
        var fileName = file.FileName;
        var fileExtend = Path.GetExtension(file.FileName).ToLower();
        var fileSizeKb = (long)(file.Length / 1024.0);

        var fileId = Guid.NewGuid();
        var fileServerName = fileId.ToString().ToLower().Replace("-", "");
        var basePath = App.WebHostEnvironment.WebRootPath;
        var time = DateTime.Now;
        var filePath = Path.Combine(basePath, "upload", time.Year.ToString(), time.ToString("MM-dd"),
            $"{fileServerName}{fileExtend}");
        var previewUrl = $"/upload/{time.Year}/{time:MM-dd}/{fileServerName}{fileExtend}";
        if (!Directory.Exists(Path.GetDirectoryName(filePath)))
            Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);

        // 对上传的文件进行本地保存
        await using (var avatarFile = File.Create(filePath))
        {
            await file.CopyToAsync(avatarFile);
            await avatarFile.FlushAsync();
        }

        // 保存数据库
        SysFile fileInput = new()
        {
            Id = fileId,
            Name = fileName,
            Extend = fileExtend,
            Size = fileSizeKb,
            Path = filePath,
            Url = previewUrl,
            Category = FileCategoryConst.ATTACHMENT
        };
        _ = await fileRep.InsertAsync(fileInput);

        return fileInput.Adapt<FileModel>();
    }

    /// <summary>
    ///     上传头像
    /// </summary>
    /// <returns></returns>
    [HttpPost("upload/avatar")]
    public async Task<FileModel> UploadAvatarAsync(IFormFile file)
    {
        if (file is null)
            throw Oops.Oh(ErrorCodeEnum.NotFile);

        // 文件名称
        var fileName = file.FileName;
        var fileExtend = Path.GetExtension(file.FileName).ToLower();
        // 文件大小KB
        var fileSizeKb = (long)(file.Length / 1024.0);

        var fileId = Guid.NewGuid();
        var fileServerName = fileId.ToString().ToLower().Replace("-", "");
        var basePath = App.WebHostEnvironment.WebRootPath;
        var filePath = Path.Combine(basePath, "avatar", UserManager.Account, $"{fileServerName}{fileExtend}");
        var previewUrl = $"/avatar/{UserManager.Account}/{fileServerName}{fileExtend}";
        if (!Directory.Exists(Path.GetDirectoryName(filePath)))
            Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);

        // 对上传的文件进行本地保存
        await using (var avatarFile = File.Create(filePath))
        {
            await file.CopyToAsync(avatarFile);
            await avatarFile.FlushAsync();
        }

        // 保存数据库
        SysFile fileInput = new()
        {
            Id = fileId,
            Name = fileName,
            Extend = fileExtend,
            Size = fileSizeKb,
            Path = filePath,
            Url = previewUrl,
            Category = FileCategoryConst.AVATAR
        };
        _ = await fileRep.InsertAsync(fileInput);

        return fileInput.Adapt<FileModel>();
    }

    /// <summary>
    ///     上传模板
    /// </summary>
    /// <returns></returns>
    [HttpPost("upload/template")]
    public async Task<FileModel> UploadTemplateAsync(IFormFile file)
    {
        if (file is null)
            throw Oops.Oh(ErrorCodeEnum.NotFile);

        // 文件名称
        var fileName = file.FileName;
        var fileExtend = Path.GetExtension(file.FileName).ToLower();
        // 文件大小KB
        var fileSizeKb = (long)(file.Length / 1024.0);

        var fileId = Guid.NewGuid();
        var fileServerName = fileId.ToString().ToLower().Replace("-", "");
        var basePath = App.WebHostEnvironment.WebRootPath;
        var filePath = Path.Combine(basePath, "template", $"{fileServerName}{fileExtend}");
        var previewUrl = $"/template/{fileServerName}{fileExtend}";
        if (!Directory.Exists(Path.GetDirectoryName(filePath)))
            Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);

        // 对上传的文件进行本地保存
        await using (var avatarFile = File.Create(filePath))
        {
            await file.CopyToAsync(avatarFile);
            await avatarFile.FlushAsync();
        }

        // 保存数据库
        SysFile fileInput = new()
        {
            Id = fileId,
            Name = fileName,
            Extend = fileExtend,
            Size = fileSizeKb,
            Path = filePath,
            Url = previewUrl,
            Category = FileCategoryConst.TEMPLATE
        };
        _ = await fileRep.InsertAsync(fileInput);

        return fileInput.Adapt<FileModel>();
    }

    /// <summary>
    ///     编辑系统文件状态
    /// </summary>
    /// <param name="data">请求参数</param>
    /// <returns></returns>
    public async Task<bool> EnableAsync(InputModel data)
    {
        return await fileRep.UpdateAsync(f => new SysFile { IsEnable = SqlFunc.IIF(f.IsEnable, false, true) },
            f => f.Id == data.Id);
    }

    /// <summary>
    ///     删除系统文件
    /// </summary>
    /// <param name="data">请求参数</param>
    /// <returns></returns>
    public async Task<bool> DelAsync(DeleteInputModel data)
    {
        return await fileRep.UpdateAsync(f => new SysFile { IsDelete = true }, f => data.Ids.Contains(f.Id));
    }

    /// <summary>
    ///     获取系统文件
    /// </summary>
    /// <param name="id">主键</param>
    /// <returns></returns>
    public async Task<FileOutput?> GetDataAsync(Guid id)
    {
        return await fileRep.AsQueryable().Where(f => f.Id == id).Select<FileOutput>().FirstAsync();
    }

    /// <summary>
    ///     分页: 系统文件集合
    /// </summary>
    /// <param name="query">请求文件</param>
    /// <returns></returns>
    public async Task<PageModel<FileOutput>> GetPageAsync([FromQuery] FilePageQuery query)
    {
        return await fileRep
            .AsQueryable()
            .LeftJoin<RelTableFile>((f, i) => f.Id == i.FileId)
            .WhereIF(!query.Name.IsNullOrEmpty(),
                f => f.Name.Contains(query.Name))
            .WhereIF(query.Date is not null && query.Date.Count == 2,
                f => f.CreateTime > Convert.ToDateTime(query.Date![0]) &&
                     f.CreateTime < Convert.ToDateTime(query.Date![1]).AddDays(1))
            .OrderByPropertyName(query.OrderField, query.IsAscending ? OrderByType.Asc : OrderByType.Desc)
            .Select((f, i) => new FileOutput { TableName = i.TableName }, true)
            .ToPageAsync(query.PageIndex, query.PageSize);
    }

    /// <summary>
    ///     下载系统文件
    /// </summary>
    /// <param name="id">文件id</param>
    /// <returns></returns>
    [HttpGet]
    [NonUnify]
    [SuppressMonitor]
    public async Task<IActionResult> DownAsync(Guid id)
    {
        var result = await GetDataAsync(id);
        _ = result ?? throw Oops.Oh(ErrorCodeEnum.NotFindFile);

        // 返回文件流
        return new FileStreamResult(File.OpenRead(result.Path), MediaTypeNames.Application.Octet)
        {
            FileDownloadName = result.Name
        };
    }
}